
import * as React from 'react';
import {
  PureComponent,
  PropTypes
} from 'react';
import * as cx from 'classnames';
import {findDOMNode} from 'react-dom';
import {
  Editor,
  EditorState,
  RichUtils,
  Modifier,
  Entity,
  CompositeDecorator,
  AtomicBlockUtils
} from 'draft-js';
import {FormsyInput} from '../../uploader/image';

import {
  getEntityAtCursor,
  clearEntityForRange
} from './util';
import {
  BLOCK_LISTS,
  ENTITY_TYPE,
  INLINE_STYLES,
  HEADINGS
} from './constants';
import {
  Dropdown,
  ButtonGroup,
  Button,
  MenuItem
} from 'react-bootstrap';
import PopOverButton from './popover-button';
import * as Input from 'formsy-react-components/release/input';


export default class Toolbar extends PureComponent {

  constructor(props) {
    super(props);

    this.state = {
      link: null
    };

    this.undo = this.undo.bind(this);
    this.redo = this.redo.bind(this);
    this.focusEditor = this.focusEditor.bind(this);
    this.setLink = this.setLink.bind(this);
    this.renderLinkPopOver = this.renderLinkPopOver.bind(this);
    this.insertImage = this.insertImage.bind(this);
    this.renderImagePopOver = this.renderImagePopOver.bind(this);
  }

  undo() {
    const {
      editorState,
      onChange
    } = this.props;

    onChange(
      EditorState.undo(editorState)
    );
  }

  redo() {
    const {
      editorState,
      onChange
    } = this.props;

    onChange(
      EditorState.redo(editorState)
    );
  }

  getEntityAtCursor() {
    const {editorState} = this.props;
    const entity = getEntityAtCursor(editorState);
    return (entity == null) ? null : Entity.get(entity.entityKey);
  }

  setLink(url) {
    const {editorState} = this.props;

    if (url) {
      const selection = editorState.getSelection();
      const entityKey = Entity.create(ENTITY_TYPE.LINK, 'MUTABLE', {url});

      this.props.onChange(
        RichUtils.toggleLink(editorState, selection, entityKey)
      );

      this.focusEditor();
    } else {
      const entity = getEntityAtCursor(editorState);

      if (entity != null) {
        let {blockKey, startOffset, endOffset} = entity;
        this.props.onChange(
          clearEntityForRange(editorState, blockKey, startOffset, endOffset)
        );
      }
    }
  }


  renderReDoUnDo() {
    const {editorState} = this.props;
    const canUndo = editorState.getUndoStack().size !== 0;
    const canRedo = editorState.getRedoStack().size !== 0;

    return (
      <ButtonGroup>
        <Button
          onClick={this.undo}
          disabled={!canUndo}
        >
          <i className="fa fa-undo" />
        </Button>
        <Button
          onClick={this.redo}
          disabled={!canRedo}
        >
          <i className="fa fa-repeat" />
        </Button>
      </ButtonGroup>
    );
  }

  renderLinkPopOver() {
    let href = '';
    let entity = this.getEntityAtCursor();

    if (entity && entity.type === ENTITY_TYPE.LINK) {
      href = entity.data.url;
    }

    return (
      <div className="form-group m-b-none">
        <Input
          name="link"
          placeholder="http://example.com/"
          value={href || ''}
          layout="elementOnly"
        />
      </div>
    );
  }

  renderLinkButtons() {
    let {editorState} = this.props;
    let selection = editorState.getSelection();
    let entity = this.getEntityAtCursor();
    let hasSelection = !selection.isCollapsed();
    let isCursorOnLink = (entity != null && entity.type === ENTITY_TYPE.LINK);
    let shouldShowLinkButton = hasSelection || isCursorOnLink;

    return (
      <ButtonGroup>
        <PopOverButton
          disabled={!shouldShowLinkButton}
          onDismiss={this.focusEditor}
          onSubmit={model => this.setLink(model.link)}
          icon="fa fa-link"
          bodyRender={this.renderLinkPopOver}
        />

        <Button
          disabled={!isCursorOnLink}
          onMouseDown={() => this.setLink(null)}
        >
          <i className="fa fa-cut" />
        </Button>
      </ButtonGroup>
    );
  }

  insertImage(src) {
    if (src) {
      const entityKey = Entity.create(ENTITY_TYPE.IMAGE, 'IMMUTABLE', {src});
      const {editorState} = this.props;

      this.props.onChange(
        AtomicBlockUtils.insertAtomicBlock(editorState, entityKey, ' ')
      );
    }
  }

  renderImagePopOver() {
    let href = '';
    let entity = this.getEntityAtCursor();

    if (entity && entity.type === ENTITY_TYPE.LINK) {
      href = entity.data.url;
    }

    return (
      <div className="form-group m-b-none">
        <FormsyInput
          name="src"
          value={href || ''}
          placeholder="点击选择图片或将图片拖入本区域!"
          reciever={this.props.reciever}
        />
      </div>
    );
  }

  renderImageButton() {
    let {editorState} = this.props;
    let selection = editorState.getSelection();

    return (
      <PopOverButton
        disabled={!selection.isCollapsed()}
        onDismiss={this.focusEditor}
        onSubmit={model => this.insertImage(model.src)}
        icon="fa fa-image"
        bodyRender={this.renderImagePopOver}
      />

    );
  }

  focusEditor() {
    // Hacky: Wait to focus the editor so we don't lose selection.
    setTimeout(() => {
      this.props.focusEditor();
    }, 50);
  }

  render() {
    const {
      editorState,
      toggleBlockStyle,
      toggleInlineStyle
    } = this.props;

    const selection = editorState.getSelection();
    const content = editorState.getCurrentContent();
    const block = content.getBlockForKey(selection.getStartKey());
    const blockType = block.getType();
    const currentStyle = editorState.getCurrentInlineStyle();


    return (
      <div className="btn-toolbar m-b-sm btn-editor">
        <Dropdown
          id="editor-pick-header"
        >
          <Dropdown.Toggle
            className={cx({
              active: /^header/.test(blockType)
            })}
          >
            <i className="fa fa-header" />
          </Dropdown.Toggle>
          <Dropdown.Menu>
            {HEADINGS.map((heading, key) => (
              <MenuItem
                active={blockType === heading.style}
                key={key}
                onClick={() => {
                  toggleBlockStyle(heading.style);
                  this.focusEditor()
                }}
              >{heading.label}</MenuItem>
            ))}
          </Dropdown.Menu>
        </Dropdown>

        <ButtonGroup>
          {INLINE_STYLES.map((inline, key) => (
            <Button
              key={key}
              onMouseDown={(e) => {
                e.preventDefault();
                toggleInlineStyle(inline.style);
              }}
              active={currentStyle.has(inline.style)}
            >
              <i className={inline.icon} />
            </Button>
          ))}
        </ButtonGroup>

        <ButtonGroup>
          {BLOCK_LISTS.map((block, key) => (
            <Button
              key={key}
              active={blockType === block.style}
              onClick={() => {
                toggleBlockStyle(block.style);
                this.focusEditor();
              }}
            ><i className={block.icon} /></Button>
          ))}
        </ButtonGroup>

        {this.renderLinkButtons()}
        {this.renderImageButton()}
        {this.renderReDoUnDo()}
      </div>
    );
  }
}